package com.huan.study.argument.config;

import com.huan.study.argument.resolver.RedisMethodArgumentResolver;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * @author huan.fu 2021/12/7 - 下午3:32
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    
    /**
     * 这个地方加载的顺序是在默认的HandlerMethodArgumentResolver之后的
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        // resolvers.add(new RedisMethodArgumentResolver());
    }
    
    /**
     * 自定义RequestMappingHandlerAdapter,但是同时保存SpringBoot MVC的配置
     * <a href="https://docs.spring.io/spring-boot/docs/current/reference/html/web.html#web">自定义RequestMappingHandlerAdapter</a>
     */
    @Component
    static class CustomWebMvcRegistrations implements WebMvcRegistrations {
        // @Override
        // public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
        //     return new RequestMappingHandlerAdapter();
        // }
    }
    
    @Component
    static class CustomHandlerMethodArgumentResolverConfig implements BeanPostProcessor {
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (bean instanceof RequestMappingHandlerAdapter) {
                final RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter) bean;
                final List<HandlerMethodArgumentResolver> argumentResolvers = Optional.ofNullable(adapter.getArgumentResolvers())
                        .orElseGet(ArrayList::new);
                final ArrayList<HandlerMethodArgumentResolver> handlerMethodArgumentResolvers = new ArrayList<>(argumentResolvers);
                handlerMethodArgumentResolvers.add(0, new RedisMethodArgumentResolver());
                adapter.setArgumentResolvers(Collections.unmodifiableList(handlerMethodArgumentResolvers));
                return adapter;
            }
            return bean;
        }
    }
}
